package com.sky.d_fork_jion;

import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

/**
 * JDK7提供ExecutorService新实现ForkJionPool
 * http://ifeve.com/fork-join-2/
 * @Author:hjt
 */
public class ForkJionPoolDemo {
	
	/**
	  实现一个任务来修改产品列表的价格
		  创建类Product，将用来存储产品的名称和价格
		  创建ProductListGenerator类，用来产生随机产品的数列
		  创建ProductTask类，指定它继承RecursiveAction类
	 */
	

	public static void main(String[] args) {
		//使用ProductListGenerator类创建一个包括10000个产品的数列
		ProductListGenerator generator = new ProductListGenerator();
		List<Product> products = generator.generate(10000);
		
		//创建一个新的ProductTask对象，用来更新产品队列中的产品。first参数使用值0，last参数使用值10000（产品数列的大小）
		ProductTask task = new ProductTask(products, 0, products.size(), 0.20);
		
		//使用无参构造器创建ForkJoinPool对象
		//会创建一个线程数等于计算机处理器数的池
		ForkJoinPool pool = new ForkJoinPool();
		
		//在池中使用execute()方法执行这个任务
		//可以提交一个Runnable对象给ForkJoinPool类。
		//注意：ForkJoinPool类不会对Runnable对象使用work-stealing算法。
		//它（work-stealing算法）只用于ForkJoinTask对象
		pool.execute(task);
		
		//实现一个显示关于每隔5毫秒池中的变化信息的代码块。将池中的一些参数值写入到控制台，直到任务完成它的执行
		do {
			System.out.printf("Main: Thread Count: %d\n",pool.getActiveThreadCount());
			System.out.printf("Main: Thread Steal: %d\n",pool.getStealCount());
			System.out.printf("Main: Parallelism: %d\n",pool.getParallelism());

			try {
				TimeUnit.MILLISECONDS.sleep(5);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} while (!task.isDone());
		
		//使用shutdown()方法关闭这个池
		pool.shutdown();
		
		//使用isCompletedNormally()方法检查假设任务完成时没有出错，在这种情况下，写入一条信息到控制台
		if(task.isCompletedNormally()){
			System.out.println("The process has completed normally");
		}
		
		//在增长之后，所有产品的价格应该是12。将价格不是12的所有产品的名称和价格写入到控制台，用来检查它们错误地增长它们的价格
		for(int i=0;i < products.size(); i++){
			Product product = products.get(i);
			if (product.getPrice() != 12){
				System.out.println("Product:" + product.getName() + "," + product.getPrice());
			}
		}
		
		//写入一条信息到控制台表明程序的结束
		System.out.println("End of the program");
		
	}

}

/**
 1.jdk7新增了并发框架-fork/join框架
 	ForkJoinTask代表一个需要执行的任务
 	真正执行这些任务的线程是放在一个线程池（ForkJoinPool）里
 	ForkJoinPool是一个可以执行ForkJoinTask的ExcuteService，
 	与ExcuteService不同的是它采用了work-stealing模式：所有在池中的线程尝试去执行其他线程创建的子任务，这样就很少有线程处于空闲状态，非常高效
 
 2.Fork/Join框架的异常处理
 	if(task.isCompletedAbnormally())
	{
	    System.out.println(task.getException());
	}
	
	isCompletedAbnormally()方法来检查任务是否已经抛出异常或已经被取消了
	getException方法获取异常
		getException方法返回Throwable对象，如果任务被取消了则返回CancellationException。
		如果任务没有完成或者没有抛出异常则返回null
		
 3.实现原理
 	3.1 fork操作：当你把任务分成更小的任务和使用这个框架执行它们
 	
 	3.2 fork方法实现原理：当我们调用ForkJoinTask的fork方法时，
 	程序会调用ForkJoinWorkerThread的pushTask方法异步的执行这个任务，然后立即返回结果
	 	pushTask方法把当前任务存放在ForkJoinTask 数组queue里。
	 	然后再调用ForkJoinPool的signalWork()方法唤醒或创建一个工作线程来执行任务
	 	
 	3.3 join操作：当一个任务等待它创建的任务的结束
 	3.4 Join方法的主要作用是阻塞当前线程并等待获取结果
 		调用了doJoin()方法，通过doJoin()方法得到当前任务的状态来判断返回什么结果，
 		任务状态有四种：已完成（NORMAL），被取消（CANCELLED），信号（SIGNAL）和出现异常（EXCEPTIONAL）。
			如果任务状态是已完成，则直接返回任务结果。
			如果任务状态是被取消，则直接抛出CancellationException。
			如果任务状态是抛出异常，则直接抛出对应的异常。
 4.Fork/Join框架的核心
 	ForkJoinPool：它实现ExecutorService接口和work-stealing算法。它管理工作线程和提供关于任务的状态和它们执行的信息。
	ForkJoinTask： 它是将在ForkJoinPool中执行的任务的基类。它提供在任务中执行fork()和join()操作的机制，并且这两个方法控制任务的状态。
	通常， 为了实现你的Fork/Join任务，你将实现两个子类的子类的类：RecursiveAction对于没有返回结果的任务和RecursiveTask 对于返回结果的任务
	

 */
